/*
 * 原版接口
 */
import * as server from "@minecraft/server";
/*
 * 蛋白石组件
 */
import * as derived_tools from "../system/derived_tools";
import * as native_tools from "../system/native_tools";
import * as math_tools from "../system/math_tools";
/**
 ** 获取周围 总线方块 的 有效数组
 * 
 * @param object - 发起事件 的 方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 * 
 * @returns {server.Block[]} 被选中的总线方块队列
 */
function CableQueue(object: server.Block, type: string): server.Block[] {
    /**
     ** 设定方块的原始数组
     */
    const getProtoArray: server.Block[] = [];
    // 获取 方块的 周围方块
    try {
        // 获取可能进行交互的方块
        const portPositive_X = object.east();
        const portNegative_X = object.west();
        const portPositive_Y = object.above();
        const portNegative_Y = object.below();
        const portPositive_Z = object.south();
        const portNegative_Z = object.north();
        /**
         ** 获取 方块的 3轴识别特征
         */
        const getPoint = type.split(/\s+/)[0].split(/-/);
        //根据 3轴特征 注入数组
        switch (getPoint[0]) {
            case 'Xx':
                if (portPositive_X?.hasTag("data_tag:magic_cable.port_negative.X")) getProtoArray.push(portPositive_X);
                if (portNegative_X?.hasTag("data_tag:magic_cable.port_positive.X")) getProtoArray.push(portNegative_X);
                break;

            case 'X':
                if (portPositive_X?.hasTag("data_tag:magic_cable.port_negative.X")) getProtoArray.push(portPositive_X);
                break;

            case 'x':
                if (portNegative_X?.hasTag("data_tag:magic_cable.port_positive.X")) getProtoArray.push(portNegative_X);
                break;

            default: break;
        };
        switch (getPoint[1]) {
            case 'Yy':
                if (portPositive_Y?.hasTag("data_tag:magic_cable.port_negative.Y")) getProtoArray.push(portPositive_Y);
                if (portNegative_Y?.hasTag("data_tag:magic_cable.port_positive.Y")) getProtoArray.push(portNegative_Y);
                break;

            case 'Y':
                if (portPositive_Y?.hasTag("data_tag:magic_cable.port_negative.Y")) getProtoArray.push(portPositive_Y);
                break;

            case 'y':
                if (portNegative_Y?.hasTag("data_tag:magic_cable.port_positive.Y")) getProtoArray.push(portNegative_Y);
                break;

            default: break;
        };
        switch (getPoint[2]) {
            case 'Zz':
                if (portPositive_Z?.hasTag("data_tag:magic_cable.port_negative.Z")) getProtoArray.push(portPositive_Z);
                if (portNegative_Z?.hasTag("data_tag:magic_cable.port_positive.Z")) getProtoArray.push(portNegative_Z);
                break;

            case 'Z':
                if (portPositive_Z?.hasTag("data_tag:magic_cable.port_negative.Z")) getProtoArray.push(portPositive_Z);
                break;

            case 'z':
                if (portNegative_Z?.hasTag("data_tag:magic_cable.port_positive.Z")) getProtoArray.push(portNegative_Z);
                break;

            default: break;
        };
    }
    catch {
        derived_tools.ErrorMessage('<§l§b 魔导总线 §r>§4 发生错误§r', object, { text: '未能获取到<§l§d 魔导总线 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用' });
    };
    //返回经过最终过滤的方块数组
    return getProtoArray.filter(
        info => {
            /**
             ** 获取方块的魔力类型
             */
            const state = info.permutation.getState('STATE:rune_type') as number;
            return state === 0
        }
    );
};

/**
 ** 赋值 队列 方块属性
 *
 * @param queue - 执行 赋值 的 方块数组
 * 
 * @param type - 进行 赋值 的 方块属性
 * 
 * @param value - 方块属性值
 * 
 * @returns {Error | void} - 赋值失败 返回 错误信息
 */
function TryQueueState(queue: server.Block[], type: string, value: string | number | boolean): Error | void {
    try {
        queue.forEach(
            block => {
                /**
                 ** 赋值 方块属性
                 */
                const state = block.permutation.withState(type, value);
                block.setPermutation(state);
            }
        )
    }
    catch (error) { return error as Error; }
};

/**
 ** 获取红石信号是否变动
 * 
 * @param object - 执行 赋值 的 方块对象
 * 
 * @param states - 方块的 默认属性
 * 
 * @returns {boolean} 方块的红石信号是否变动
 */
function Redstone(object: server.Block, states: server.BlockPermutation): boolean {
    try {
        /**
         ** 获取方块的红石能量
         */
        const getRedstoneBlock = object.above()?.getRedstonePower();
        /**
         ** 获取自身保存的对比值
         */
        const getRedstoneSelf = states.getState('STATE:redstone') as number;
        //监测数值是否相等
        if (getRedstoneBlock != undefined) {
            if (getRedstoneBlock === getRedstoneSelf) {
                return true
            }
            else {
                native_tools.TrySetPermutation(object, 'STATE:redstone', getRedstoneBlock);
                return false
            }
        }
        else {
            native_tools.TrySetPermutation(object, 'STATE:redstone', 0);
            return true
        }
    }
    catch {
        return false
    }
};
/**
 ** 红石侦测
 * 
 * @param object - 执行 赋值 的 方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 */
export function RedstoneDetection(object: server.Block, type: string) {
    if (!Redstone(object, object.permutation)) TryQueueState(CableQueue(object, type), 'STATE:rune_type', math_tools.Random({ max: 7, min: 1 }, true));
};

/**
 ** 检测方块朝向
 * 
 * @param {server.Vector3} source 需要检测的方块朝向
 */
function RunDetection(object: server.Block, source: server.Vector3) {
    // 遍历 32 个方块
    for (let index = 1; index < 32; index++) {
        /**
         ** 获取方块对象
         */
        const getBlock = object.offset({ x: source.x * index, y: source.y * index, z: source.z * index });
        /**
         ** 获取方块 的 魔力类型
         */
        const state = (getBlock?.permutation.getState('STATE:rune_type') as number) ?? 9;
        // 检查方块是否符合要求
        if (!getBlock?.hasTag('data_tag:magic_cable.series') || state != 0) continue;
        // 设置方块属性
        native_tools.TrySetPermutation(getBlock, 'STATE:rune_type', object.permutation.getState('STATE:rune_type') as number);
        //保存方块对象
        return getBlock;
    };
    return object
};
/**
 ** 超导髓鞘 
 * 
 * @returns {server.Block} 方块对象
 */
export function SuperPulse(object: server.Block, type: string): server.Block {
    //执行模块功能
    try {
        // 设置方块属性
        server.system.run(() => native_tools.TrySetPermutation(object, 'STATE:rune_type', 9));
        // 获取方块朝向
        switch (type) {
            case 'up': return RunDetection(object, math_tools.Vector.CONSTANT_UP);

            case 'down': return RunDetection(object, math_tools.Vector.CONSTANT_DOWN);

            case 'east': return RunDetection(object, math_tools.Vector.CONSTANT_EAST);

            case 'west': return RunDetection(object, math_tools.Vector.CONSTANT_WEST);

            case 'north': return RunDetection(object, math_tools.Vector.CONSTANT_NORTH);

            case 'south': return RunDetection(object, math_tools.Vector.CONSTANT_SOUTH);

            default: return object;
        };
    }
    // 异常处理, 显示错误信息
    catch {
        derived_tools.ErrorMessage('<§l§b 超导髓鞘 §r>§4 发生错误§r', object, { text: '无法发送<§l§c 总线信号 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用!!' });
        //返回方块对象
        return object;
    };
};

/**
 ** 超导枢纽
 */
export function SuperOmphalos(object: server.Block, states: server.BlockPermutation) {
    // 遍历 6 个方向 的 方块
    try {
        ['up', 'down', 'north', 'south', 'west', 'east'].forEach(
            // 替换指定方向的方块
            info => native_tools.TryFillBlocks(
                object.dimension,
                math_tools.Vector.add(object, { x: 11, y: 11, z: 11 }),
                math_tools.Vector.add(object, { x: -11, y: -11, z: -11 }),
                server.BlockPermutation.resolve('block_cable:super_pulse',
                    {
                        "STATE:rune_type": states.getState('STATE:rune_type') as number,
                        "minecraft:block_face": info
                    }
                ),
                {
                    blockFilter: {
                        includePermutations: [
                            server.BlockPermutation.resolve('block_cable:super_pulse',
                                {
                                    "STATE:rune_type": 0,
                                    "minecraft:block_face": info
                                }
                            )
                        ]
                    }
                }
            )
        )
    }
    // 异常处理, 显示错误信息
    catch {
        derived_tools.ErrorMessage('<§l§b 超导枢纽 §r>§4 发生错误§r', object, { text: '无法发送<§l§c 总线信号 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用!!' });
    };
    //复位自身状态
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
};

/**
 ** 信号编译
 */
export function SignalCompilation(object: server.Block, type: string, states: server.BlockPermutation) {
    /**
     ** 异常处理
     */
    const onError = () => {
        object.setPermutation(object.permutation.withState('STATE:stage', 2));
        object.setPermutation(object.permutation.withState('STATE:index', 0));
        derived_tools.ErrorMessage('<§l§b 信号编译 §r>§4 发生错误§r', object, { text: '未能在设备上方找到合适的<§l§3 方块容器 §r>' });
    };
    /**
     ** 获取上方方块对象
     */
    const aboveBlock = object.above();
    /**
     ** 获取 物品容器
     */
    const getContainer = aboveBlock?.getComponent('minecraft:inventory')?.container;
    /**
     ** 获取 物品容器 索引
     */
    const getSlot = states.getState('STATE:index') as number;
    //确认 容器 真实存在
    if (!getContainer) return onError();
    // 检查 物品容器 索引 是否超出范围 或  索引 是否为 15
    if (getSlot >= getContainer.size || getSlot == 15) {
        native_tools.TrySetPermutation(object, 'STATE:stage', 2);
        native_tools.TrySetPermutation(object, 'STATE:index', 0);
        return;
    };
    const blocks = CableQueue(object, type);
    //根据获得参数 进行 方块属性 设置
    switch (getContainer.getItem(getSlot)?.typeId) {
        case 'item_crystal:blue_energy': TryQueueState(blocks, 'STATE:rune_type', 1); break;

        case 'item_crystal:red_energy': TryQueueState(blocks, 'STATE:rune_type', 2); break;

        case 'item_crystal:green_energy': TryQueueState(blocks, 'STATE:rune_type', 3); break;

        case 'item_crystal:orange_energy': TryQueueState(blocks, 'STATE:rune_type', 4); break;

        case 'item_crystal:purple_energy': TryQueueState(blocks, 'STATE:rune_type', 5); break;

        case '能量水晶:白星_魔晶石': TryQueueState(blocks, 'STATE:rune_type', 6); break;

        case '能量水晶:黑渊_魔晶石': TryQueueState(blocks, 'STATE:rune_type', 7); break;

        default: TryQueueState(blocks, 'STATE:rune_type', 0); break;
    };
    // 修改 物品容器 索引
    native_tools.TrySetPermutation(object, 'STATE:index', getSlot + 1);
};

/**
 ** 交互终端
 * 
 * @param object - 发起事件的方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 * 
 * @param states - 方块 的 状态属性
 */
export function interactiveTerminal(object: server.Block, type: string, states: server.BlockPermutation) {
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
};

/**
 ** 逻辑元件
 * 
 * @param object - 发起事件的方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 */
export function logicComponents(object: server.Block, type: string) {
    /**
     ** 获取 魔导总线队列
     */
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', math_tools.Random({ max: 7, min: 1 }, true));
    if (object.typeId == 'block_cable:logic_inverter') return;
    // 重置逻辑锁存器
    for (let axleX = -1; axleX <= 1; axleX++) for (let axleY = -1; axleY <= 1; axleY++) for (let axleZ = -1; axleZ <= 1; axleZ++) {
        /**
         ** 获取方块对象
         */
        const block = object.offset({ x: axleX, y: axleY, z: axleZ });
        if (block?.typeId == 'block_cable:pulse_latch') native_tools.TrySetPermutation(block, 'STATE:rune_note', 0);
    };
};

/**
 ** 信号处理
 * 
 * @param object - 发起事件的方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 * 
 * @param states - 方块 的 状态属性
 */
export function signalProcessing(object: server.Block, type: string, states: server.BlockPermutation) {
    /**
     ** 获取 魔导总线队列
     */
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
};

/**
 ** 逻辑单通
 * 
 * @param {server.Block} object - 发起事件的方块对象
 */
function logicSingle(object: server.Block) {
    const direction = object.permutation.getState('minecraft:block_face') as string;
    function detection_up() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_UP);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_DOWN);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    function detection_down() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_DOWN);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_UP);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    function detection_north() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_NORTH);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_SOUTH);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    function detection_south() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_SOUTH);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_NORTH);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    function detection_west() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_WEST);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_EAST);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    function detection_east() {
        /**
         ** 属性输入
         */
        const input = object.offset(math_tools.Vector.CONSTANT_EAST);
        /**
         ** 属性输出
         */
        const output = object.offset(math_tools.Vector.CONSTANT_WEST);
        if (!input || !input?.hasTag('data_tag:magic_cable.open')) return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series')) return;
        /**
         ** 方块属性
         */
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note') as number);
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    };
    switch (direction) {
        case 'up': detection_up(); break;

        case 'down': detection_down(); break;

        case 'north': detection_north(); break;

        case 'south': detection_south(); break;

        case 'west': detection_west(); break;

        case 'east': detection_east(); break;

        default: break;
    }
};

/**
 ** 逻辑锁存器更新事件
 * 
 * @param object - 发起事件的方块对象
 */
export function LatchUpdateEvent(object: server.Block) {
    /**
     ** 执行 方块更新事件 的 方块列表
     */
    const blocks: server.Block[] = [];
    // 获取 进行更新的方块
    for (let axleX = -1; axleX <= 1; axleX++) for (let axleY = -1; axleY <= 1; axleY++) for (let axleZ = -1; axleZ <= 1; axleZ++) {
        const Pointer = object.offset({ x: axleX, y: axleY, z: axleZ });
        if (Pointer) blocks.push(Pointer);
    };
    // 遍历 方块列表
    blocks.forEach(
        block => {
            switch (block.typeId) {
                case 'block_cable:logic_single': logicSingle(block); break;

                case 'block_cable:logical_and': native_tools.TrySetPermutation(block, 'STATE:stage', 1); break;

                case 'block_cable:exclusive_or': native_tools.TrySetPermutation(block, 'STATE:stage', 1); break;

                default: break;
            }
        }
    )
};

/**
 ** 默认事件
 * 
 * @param object - 发起事件的方块对象
 * 
 * @param type - 方块队列的 3轴识别特征
 * 
 * @param state - 方块 的 状态属性
 */
export function defaultEvent(object: server.Block, type: string, state: server.BlockPermutation) {
    /**
     ** 获取 方块队列
     */
    const blocks = CableQueue(object, type);
    // 遍历 方块队列
    TryQueueState(blocks, 'STATE:rune_type', state.getState('STATE:rune_type') as number);
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
};